#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "cl.h"
#include "../../test/client.h"
#include "../../test/sockcomADT.h"
#include "../../test/clsv.h"
#include "./scanADT/scanadt.h"
#include "./scanADT/strlib.h"

/* List types definitions */
enum {
	LIST_CAT, LIST_USR
};


/* get input line */
int
input(char * prompt, char * inpbuf)
{
	char c;
	int count= 0;

	/* print prompt */
	printf("%s", prompt);

	forever
	{
		c= getchar();

		if( count < MAXLINE )
			inpbuf[count++]= c;

		if( c == '\n' && count < MAXLINE )
		{
			inpbuf[count]= '\0';
			return count;
		}
		if( c == '\n' )
		{
			printf("Input line too long (Max: 511 characters).\n");
			printf("%s", prompt);
			count= 0;
		}
	}
}

/* process input line */
int
process_line(char * line)
{
	int i, narg= 0;
	char * arg[MAXARGS+1], delim[]= " ";
	char * token= NULL;
	scannerADT scanner;

	if( checkLine(line) )
	{
		printf("fish: no such command\n");
		return 0;
	}	
	scanner= NewScanner();
	SetScannerString(scanner, line);	

	while( MoreTokensExist(scanner) )
	{
		token= ReadToken(scanner);
		if( (arg[narg]= malloc(strlen(token))) == NULL )
		{
			freeArg(arg, narg-1);
			return 1;
		}
		strcpy(arg[narg++], token);
	}
	if( (i= process_command(narg, arg)) == 0 )
		printf("fish: no such command\n");
	else if( i < 0 )
	{
		freeArg(arg, narg);
		return 1;
	}
	FreeScanner(scanner);
	freeArg(arg, narg);
	return 0;
}

int
checkLine(char * line)
{
	int count= 0;

	while( *line != '\0' )
	{
		if( count != 0 && *line == '"' && count%2 == 0 && *(line-1) != ' ' && *(line-1) != '\t')
			return 1;
		if( *line == '"' && count%2 != 0 && *(line+1) != ' ' && *(line+1) != '\n' && *(line+1) != '\t' )
			return 1;
		if( *line == '"' )
			count++;
		line++;
	}
	if( count%2 == 0 )
		return 0;
	return 1;
}

int
process_command(int argc, char * argv[])
{
	int opcode= 1;

	if( !argc )					/* If there are no arguments, do nothing */
		return 1;
	
	if (strcmp(STRLOGIN, argv[0]) == 0)				/* login */
	{
		if (argc != 2)
		{
			printf("Usage: login username\n");
			return 1;
		}
		
		login(argv[1], _TCP_);	
		return ELOGIN;
	}
	
	/*
	 Download
	else if (strcmp(STRDOWNL, argv[0]) == 0)
	{
		if (argc != 3)
		{
			printf("Usage: download dest src\n");
			return 1;
		}
		run_command(EDOWNL, argv);
		return 3;
	}
	*/
	else if (strcmp(STRUPLAD, argv[0]) == 0)		/* upload */
	{
		if (argc != 3)
		{
			printf("Usage: upload filename categoryc\n");
			return 1;
		}
		run_command(EUPLAD, argv);
		return 4;
	}
	else if (strcmp(STRLISTC, argv[0]) == 0)			/* list categories */
	{
		if (argc != 1)
		{
			printf("Usage: %s\n", STRLISTC);
			return 1;
		}		
		run_command(ECAT, argv);
		
		return ECAT;
	}
	else if (strcmp(STRLISTU, argv[0]) == 0)			/* list users */
	{
		if (argc != 1)
		{
			printf("Usage: %s\n", STRLISTU);
			return 1;
		}		
		run_command(EUSERS, argv);
		
		return EUSERS;
	}
	else if (strcmp(STRLISTF, argv[0]) == 0)			/* list files */
	{
		if (argc != 2)
		{
			printf("Usage: %s category\n", STRLISTF);
			return 1;
		}		
		run_command(EFILES, argv);
		
		return EFILES;
	}
	else if (strcmp(STRGTICK, argv[0]) == 0)		/* get a ticket */
	{
		if (argc != 2)
		{
			printf("Usage: %s filename\n", STRGTICK);
			return 1;
		}
		run_command(EGTICK, argv);
		return EGTICK;
	}
	else if (strcmp(STRUTICK, argv[0]) == 0)		/* useticket */
	{
		if (argc != 3)
		{
			printf("Usage: %s ticket filename\n", STRUTICK);
			return 1;
		}
		run_command(EUTICK, argv);
		return EUTICK;
	}	
	else if (strcmp(STRPASSWD, argv[0]) == 0)
	{
		if (argc > 2 || (argc == 2 && strcmp(argv[1], "-u")))
		{
			printf("Usage: passwd [-u]\n");
			return 1;
		}
		if (argc == 1)
			changePass(_TCP_);
		else if (argc == 2)
			changePass(_UDP_);
		return 8;
	}
	else if (strcmp(STRLEAVE, argv[0]) == 0)		/* quit */
	{
		if( argc != 1 )
		{
			printf("Usage: quit\n");
			return 1;
		}
		return -1;
	}
	return 0;
}

void
run_command(int command, char * argv[])
{
	if (!start_session(COMM_CLIENT))
	{
		fprintf(stderr, "Sockets creation failed\n");
		return;
	}
	switch (command)
	{
		case EUPLAD:
			uploadFile(argv[1], argv[2]); break;
		case ECAT:
			listCategories(); break;
		case EUSERS:
			listUsers(); break;
		case EFILES:
			listFiles(argv[1]); break;
		case EGTICK:
			getTicket(argv[1]); break;
		case EUTICK:
			useTicket(argv[1], argv[2]); break;
	}
	end_session();
}

void
freeArg(char ** arg, int narg)
{
	int i;

	if( narg < 1 )
		return;
	for( i= 0; i < narg; i++ )
		free(arg[i]);
	return;
}
